module App::Controller
    class TogglTree < Qt::Object
        slots 'itemActivated(const QModelIndex)'
        slots 'newItemInserted(const QModelIndex)'
        slots 'refreshModelBegin(const QAbstractItemModel *)'
        slots 'refreshModelEnd(const QAbstractItemModel *)'
        slots 'rightClick(QPoint)', :clientAdd, :projectAdd, :taskAdd, :taskDelete, :editTriggered
        slots 'newItemInline(QWidget*)'

        def initialize(view)
            super()

            @treeview = view

            connect view, SIGNAL('activated(const QModelIndex)'),
                              self, SLOT('itemActivated(const QModelIndex)')
            connect view, SIGNAL('customContextMenuRequested(const QPoint)'),
                              self, SLOT('rightClick(const QPoint)')
            
            connect view.model, SIGNAL('rowsInserted(const QModelIndex, int, int)'),
                              self, SLOT('newItemInserted(const QModelIndex)')
            connect view.model, SIGNAL('refreshModelBegin(const QAbstractItemModel *)'),
                              self, SLOT('refreshModelBegin(const QAbstractItemModel *)')
            connect view.model, SIGNAL('refreshModelEnd(const QAbstractItemModel *)'),
                              self, SLOT('refreshModelEnd(const QAbstractItemModel *)')

            connect view.model, SIGNAL('itemChanged(QStandardItem*)'),
                              view, SLOT('itemChanged(QStandardItem*)')
            connect view.model, SIGNAL('columnsInserted(QModelIndex, int, int)'),
                              view, SLOT('modelColumnsModified()')
            
            #connect tv.itemDelegate, SIGNAL('commitData(QWidget*)'),
            #                  self, SLOT('newItemInline(QWidget*)')
        end

        def filter_clients
            @treeview.model.eachClient { |client|
                if $widget.model.ignored_clients.ignored?(client.text)
                    puts "Mr. Hide: #{client.text}"
                    @treeview.setRowHidden(client.row, @treeview.model.invisibleRootItem.index, true)
                end
            }
        end

        private
        def itemActivated(mi)
            item = mi.model.itemFromIndex mi
            #puts "activated: #{item}"
            case item
            when App::Items::Client
                # QtRuby anti-segfault hack..
                unless @treeview.is_expanded(mi)
                    @treeview.set_expanded(mi, true)
                else
                    $nic.dispose if $nic
                    $nic = App::Controller::New.new item, App::Items::Project
                end
            when App::Items::Project
                unless @treeview.is_expanded(mi)
                    @treeview.set_expanded(mi, true)
                else
                    $nic.dispose if $nic
                    $nic = App::Controller::New.new item
                end
            when App::Items::Task
                return if item.taken
                begin
                    item.toggle
                rescue App::CommunicationError => e
                    App::View::ErrorDialog.new($widget.view, e)
                    $widget.quit
                end
            end
        end

        def newItemInserted(parentMI)
            return unless parentMI.model
            parentitem = parentMI.model.itemFromIndex parentMI
            #puts "newItemInserted below parentitem: #{parentitem}"
            @treeview.setExpanded parentMI, true unless parentitem.is_a? App::Items::Task
        end

        def refreshModelBegin(model)
            return unless model == @treeview.model
            disconnect model, SIGNAL('rowsInserted(const QModelIndex, int, int)'),
                              self, SLOT('newItemInserted(const QModelIndex)')
        end
        def refreshModelEnd(model)
            return unless model == @treeview.model
            connect model, SIGNAL('rowsInserted(const QModelIndex, int, int)'),
                              self, SLOT('newItemInserted(const QModelIndex)')

            # Avoid flickering
            $watchdog.colorize_tasks if $watchdog

            # Expand to the running task
            item = @treeview.model.getRunningTask
            while item = item.parent
                @treeview.set_expanded @treeview.model.indexFromItem(item), true
            end if item

            filter_clients
        end

        def rightClick(point)
            # TODO
            # We should find the item below the mouse cursor instead of the
            # selected one. Karm also works in this way. I dunno how to do that.
            #  -pallair

            item, mi = getSelectedItem
            return if not item or item.class == Qt::StandardItem
            debugmi = @treeview.selectionModel.currentIndex
            debugitem = debugmi.model.itemFromIndex debugmi
            #puts "Rightclick, row's 1st item is #{item} (data: #{mi.data.toString})"
            #puts "It's a: #{debugitem} at #{debugmi.row},#{debugmi.column}"

            @menu.dispose if @menu
            @menu = menu = Qt::Menu.new("customMenu")
            case item
            when App::Items::Client
                a = menu.addAction "New Client..."
                a.connect(SIGNAL(:triggered)) { clientAdd }
                b = menu.addAction "New Project..."
                b.connect(SIGNAL(:triggered)) { projectAdd }
                a = menu.addAction "Delete"
                a.setEnabled false  # see Toggl comment
            when App::Items::Project
                a = menu.addAction "New Task..."
                connect a, SIGNAL('triggered()'), self, SLOT('taskAdd()')
                a = menu.addAction "Delete"
                a.setEnabled false  # see Toggl comment
            when App::Items::Task
                a = menu.addAction "New Task..."
                connect a, SIGNAL('triggered()'), self, SLOT('taskAdd()')
                a = menu.addAction "Delete"
                connect a, SIGNAL('triggered()'), self, SLOT('taskDelete()')
                a = menu.addAction "Edit Task..."
                connect a, SIGNAL('triggered()'), self, SLOT('editTriggered()')
                a.setEnabled false if item.started?
            end

            #p @tv.header.height
            point.setX(point.x + 5)
            point.setY(point.y + @treeview.header.height)
            menu.popup @treeview.mapToGlobal(point)
        end

        def taskAdd()
            item, mi = getSelectedItem
            $nic.dispose if $nic
            $nic = App::Controller::New.new item
        end
        def projectAdd()
            item, mi = getSelectedItem
            $nic.dispose if $nic
            $nic = App::Controller::New.new item, App::Items::Project
        end
        def clientAdd()
            $nic.dispose if $nic
            $nic = App::Controller::New.new nil, App::Items::Client
        end
        def taskDelete()
            item, mi = getSelectedItem
            item.destroy
        end
        def editTriggered()
            item, mi = getSelectedItem
            $edit.dispose if $edit
            $edit = App::Controller::Edit.new item
        end

        # Inline adding not-so-cool in my experience
#        def newItemInline(editor)
#            midx = @tv.selectionModel.currentIndex
#            item = midx.model.itemFromIndex midx
#            puts "additeminline!", item.parent
#            name = editor.text
#            item.setText CPTModel::NewProjectItemText if item.parent.class == Client
#            item.setText CPTModel::NewTaskItemText if item.parent.class == Project
#            $worker.addItem item.parent.childClass.to_s, item.parent, name
#        end

        def getSelectedItem()
            # ennek mindig az elso oszlop itemjet kell visszaadni
            #midx = @tv.selectionModel.currentIndex
            mi = @treeview.selectionModel.selectedRows.first
            return unless mi
            item = mi.model.itemFromIndex mi
            #puts "getSelectedItem:", mi, item
            return item, mi
        end
    end
end
